package group.raber.jeki.autoconfigure;

import group.raber.jeki.autoconfigure.beetl.template.BeetlTemplateProperties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.beetl.core.ResourceLoader;
import org.beetl.core.TemplateEngineFactory;
import org.beetl.core.resource.ClasspathResourceLoader;
import org.beetl.core.resource.WebAppResourceLoader;
import org.beetl.ext.spring.BeetlGroupUtilConfiguration;
import org.beetl.ext.spring.BeetlSpringViewResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.template.TemplateLocation;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import javax.annotation.PostConstruct;
import javax.servlet.Servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by tisir<yangsong158@qq.com> on 2017-05-01
 */
@Configuration
@ConditionalOnClass({org.beetl.core.Configuration.class ,TemplateEngineFactory.class})
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties(BeetlTemplateProperties.class)
public class BeetlTemplateAutoConfiguration {

    private static final Log logger = LogFactory.getLog(BeetlTemplateAutoConfiguration.class);

    private final ApplicationContext applicationContext;

    private final BeetlTemplateProperties properties;

    public BeetlTemplateAutoConfiguration(ApplicationContext applicationContext,BeetlTemplateProperties properties) {
        this.applicationContext = applicationContext;
        this.properties = properties;
    }

    @PostConstruct
    public void checkTemplateLocationExists() {
        if (this.properties.isCheckTemplateLocation()) {
            TemplateLocation templatePathLocation = null;
            List<TemplateLocation> locations = new ArrayList<TemplateLocation>();
            String templateLoaderPath = this.properties.getTemplateLoaderPath();
            TemplateLocation location = new TemplateLocation(templateLoaderPath);
            locations.add(location);
            if (location.exists(this.applicationContext)) {
                templatePathLocation = location;
            }

            if (templatePathLocation == null) {
                logger.warn("Cannot find template location(s): " + locations
                        + " (please add some templates, "
                        + "check your Beetl configuration, or set "
                        + "spring.beetl.checkTemplateLocation=false)");
            }
        }
    }


    protected static class BeetlConfiguration {

        @Autowired
        protected BeetlTemplateProperties properties;

        protected void applyProperties(BeetlGroupUtilConfiguration factory) {
            ResourcePatternResolver patternResolver = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader());
            try {
//                factory.setConfigFileResource(patternResolver.getResource("classpath:beetl.properties"));
                String root =  patternResolver.getResource(properties.getTemplateLoaderPath()).getFile().toString();
                ResourceLoader resourceLoader = new WebAppResourceLoader(root);
//                ResourceLoader resourceLoader = new ClasspathResourceLoader(root); //换成这个之后,beetl模板引擎在web环境下,不能被加载
                factory.setResourceLoader(resourceLoader);
                factory.setRoot(properties.getTemplateLoaderPath());
//              patternResolver.getResource("classpath:beetl.properties"
                factory.setConfigFileResource(patternResolver.getResource(properties.getConfigFileResource()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    @Configuration
    @ConditionalOnClass(Servlet.class)
    @ConditionalOnWebApplication
    @ConditionalOnProperty(name = "spring.beetl.enabled", matchIfMissing = true)
    public static class BeetlWebConfiguration extends BeetlConfiguration{

        @Bean(initMethod = "init", name = "beetlConfig")
        public BeetlGroupUtilConfiguration getBeetlGroupUtilConfiguration() {

            BeetlGroupUtilConfiguration beetlGroupUtilConfiguration = new BeetlGroupUtilConfiguration();
            applyProperties(beetlGroupUtilConfiguration);

            return beetlGroupUtilConfiguration;

        }

        @Bean
        @ConditionalOnMissingBean(name = "beetlViewResolver")
        public BeetlSpringViewResolver groovyMarkupViewResolver(@Qualifier("beetlConfig") BeetlGroupUtilConfiguration beetlGroupUtilConfiguration) {

            BeetlSpringViewResolver viewResolver = new BeetlSpringViewResolver();
            this.properties.applyToViewResolver(viewResolver);
            viewResolver.setConfig(beetlGroupUtilConfiguration);
            viewResolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
            return viewResolver;
        }

    }
}
